package com.miracle9.game.server.message;

import com.miracle9.game.entity.Admin;
import com.miracle9.game.entity.AdminLog;
import com.miracle9.game.service.AdminLogService;
import com.miracle9.game.service.AdminService;
import com.miracle9.game.util.ClientIpProcess;
import com.miracle9.game.util.MyApplicationContext;
import com.miracle9.game.util.MyUtil;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;

import java.io.ByteArrayInputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service("manageSocketHandler")
public class ManageSocketHandler implements IoHandler {

    private Logger logger = Logger.getLogger(ManageSocketHandler.class);

    public void exceptionCaught(IoSession session, Throwable arg1) throws Exception {
        this.logger.error("", arg1);
        session.close(true);
    }

    public void messageReceived(IoSession session, Object message) throws Exception {
        try {
//            logger.info("管理后台服务器收到的管理后台客户端的信息" + session + message.toString());
            IoBuffer in = (IoBuffer) message;

            byte[] dataLength = new byte[4];
            in.get(dataLength);

            String str = new String(dataLength).trim();
            if (str.equals("<pol")) {
                byte[] policyStrBytes = com.miracle9.game.util.GameParameterAssist.bf.getBytes();

                IoBuffer bb = IoBuffer.allocate(policyStrBytes.length + 1);
                bb.put(policyStrBytes);
                bb.put((byte) 0);
                bb.flip();
                session.write(bb);

                this.logger.info("policy file sent: " + session.getRemoteAddress());
                session.close(true);
            } else if (str.equals("tgw_")) {
                byte[] infoBytes = new byte[in.limit()];
                in.clear();
                in.get(infoBytes);

                this.logger.info("tgw send:" + new String(infoBytes).trim());
            } else {
                in.clear();
                int length = in.getInt();
                byte[] contentBytes = new byte[length];
                in.get(contentBytes);

                contentBytes = MyUtil.Base64Decode_session(contentBytes, session);

                Amf3Input ai = new Amf3Input(SerializationContext.getSerializationContext());
                ai.setInputStream(new ByteArrayInputStream(contentBytes));
                HashMap map = (HashMap) ai.readObject();

                JsonConfig jsonConfig = new JsonConfig();
                jsonConfig.registerJsonValueProcessor(Double.class, new JsonValueProcessor() {
                    @Override
                    public Object processArrayValue(Object o, JsonConfig jsonConfig) {
                        if (o instanceof Double) {
                            if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
                                return ((Double) o).toString();
                            }
                        }
                        return o;
                    }
                    @Override
                    public Object processObjectValue(String s, Object o, JsonConfig jsonConfig) {
                        if (o instanceof Double) {
                            if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
                                return o.toString();
                            }
                        }
                        return o;
                    }
                });

                //logger.info(JSONObject.fromObject(map));

                String url = (String) map.get("method");
                Object[] args = (Object[]) map.get("args");
                double time = (Double) map.get("time");

                String version = (String) map.get("version");
                if ((version == null) || (com.miracle9.game.util.GameParameterAssist.aD.compareTo(version) > 0)) {
                    this.logger.info("disallow this client to send request,client version:" + version);
                    session.close(true);
                    return;
                }
                if (System.currentTimeMillis() - time >= 5000.0D) {
                    this.logger.info("请求时间大于5秒");
                    return;
                }
                String[] urls = url.split("/");
                String beanId = urls[0];
                String method = urls[1];
                String argsStr = method + "请求参数：";
                for (Object o : args) {
                    argsStr = argsStr + o + ";";
                }
                if (!"heart".equalsIgnoreCase(method)) {
                    //this.logger.info("管理后台服务器收到 url:" + url);
//                    this.logger.info("args：" + argsStr);
                }
                if ((!com.miracle9.game.util.GameParameterAssist.be.containsValue(session)) && (!"login_getEncrytKey".equals(method)) && (!"adminLogin".equals(method))) {
//                    this.logger.info("未登录操作");
                    return;
                }
                boolean needChanged = false;
                Object[] args_login = new Object[args.length + 1];
                for (int i = 0; i < args.length; i++) {
                    if ((args[i] instanceof com.miracle9.game.biz.manage.bean.Pager)) {
                        this.logger.info("com.miracle9.game.biz.manage.bean.Pager");
                        com.miracle9.game.bean.Pager tempObj = new com.miracle9.game.bean.Pager();
                        com.miracle9.game.biz.manage.bean.Pager pager = (com.miracle9.game.biz.manage.bean.Pager) args[i];
                        tempObj.setList(pager.getList());
                        tempObj.setOrder(pager.getOrder());
                        tempObj.setOrderBy(pager.getOrderBy());
                        tempObj.setPageCount(pager.getPageCount());
                        tempObj.setPageNumber(pager.getPageNumber());
                        tempObj.setPageSize(pager.getPageSize());
                        tempObj.setTotalCount(pager.getTotalCount());
                        args_login[i] = tempObj;
                        needChanged = true;
                    } else if (("updateGameStatus".equalsIgnoreCase(method)) && ((args[i] instanceof com.miracle9.game.biz.manage.bean.GameStatus))) {
                        com.miracle9.game.bean.GameStatus tempObj = new com.miracle9.game.bean.GameStatus();
                        com.miracle9.game.biz.manage.bean.GameStatus gameStatus = (com.miracle9.game.biz.manage.bean.GameStatus) args[i];
                        tempObj.statusIndex = gameStatus.statusIndex;
                        tempObj.time = gameStatus.time;
                        tempObj.content = gameStatus.content;
                        tempObj.cooperateMode = gameStatus.cooperateMode;
                        tempObj.cooperateStartDate = gameStatus.cooperateStartDate;
                        tempObj.cooperateEndDate = gameStatus.cooperateEndDate;
                        args_login[i] = tempObj;
                    } else {
                        args_login[i] = args[i];
                    }
                }
                args_login[(args_login.length - 1)] = session;
                args = args_login;
                if ("memberService".equalsIgnoreCase(beanId)) {
                    beanId = "userService";
                    if ("addSpecialUser".equalsIgnoreCase(method)) {
                        beanId = "specialUserService";
                    }
                }
                if ("giftLogService".equalsIgnoreCase(beanId)) {
                    beanId = "userService";
                }
                Object service = MyApplicationContext.a().getBean(beanId);
                Method m = service.getClass().getDeclaredMethod(method, getClasses(args));
                if (needChanged) {
                    for (int i = 0; i < args.length; i++) {
                        if ((args[i] instanceof com.miracle9.game.bean.Pager)) {
                            com.miracle9.game.biz.manage.bean.Pager tempObj = new com.miracle9.game.biz.manage.bean.Pager();
                            com.miracle9.game.bean.Pager pager = (com.miracle9.game.bean.Pager) args[i];
                            tempObj.setList(pager.getList());
                            tempObj.setOrder(pager.getOrder());
                            tempObj.setOrderBy(pager.getOrderBy());
                            tempObj.setPageCount(pager.getPageCount());
                            tempObj.setPageNumber(pager.getPageNumber());
                            tempObj.setPageSize(pager.getPageSize());
                            tempObj.setTotalCount(pager.getTotalCount());
                            args_login[i] = tempObj;
                            needChanged = true;
                        } else {
                            args_login[i] = args[i];
                        }
                    }
                    args = args_login;
                }
                Object result = m.invoke(service, args);
                if (result != null) {
                    AmfMessageSend.storageMethodOperating.notifyAllOperating(new StorageMethodEntity(session, method, new Object[]{result}));
                }
            }
        } catch (Exception e) {
            this.logger.error("", e);
        }
    }

    private Class<?>[] getClasses(Object[] args) {
        try {
            Class[] classArray = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                classArray[i] = args[i].getClass();
                if ((args[i] instanceof Integer)) {
                    classArray[i] = Integer.TYPE;
                } else if ((args[i] instanceof Boolean)) {
                    classArray[i] = Boolean.TYPE;
                } else if ((args[i] instanceof Map)) {
                    classArray[i] = Map.class;
                } else if ((args[i] instanceof Long)) {
                    classArray[i] = Long.TYPE;
                } else if ((args[i] instanceof Double)) {
                    classArray[i] = Double.TYPE;
                } else if ((args[i] instanceof IoSession)) {
                    classArray[i] = IoSession.class;
                } else if ((args[i] instanceof Float)) {
                    classArray[i] = Float.TYPE;
                }
            }
            return classArray;
        } catch (Exception e) {
            this.logger.error("", e);
        }
        return null;
    }

    public void messageSent(IoSession arg0, Object arg1) throws Exception {
        //logger.info("管理后台服务器发送给管理后台客户端的信息" + arg0 + arg1);
    }

    public void sessionClosed(IoSession session) throws Exception {
        Object id = session.removeAttribute("id");
        if (id != null) {
            com.miracle9.game.util.GameParameterAssist.be.remove(Integer.valueOf(id.toString()));
            session.removeAttribute("username");
            AdminService adminService = (AdminService) MyApplicationContext.a().getBean("adminService");
            Admin admin = adminService.getAdmin(Integer.valueOf(id.toString()).intValue());
            AdminLog adminLog = new AdminLog();
            adminLog.setAdmin(admin.getUsername());
            adminLog.setAuthority(admin.getType());
            adminLog.setDatetime(MyUtil.dateFormatYMD_HMS_Sting(new Date()));
            adminLog.setType(2);
            adminLog.setContent("退出管理后台");
            adminLog.setContentEn("Logout");
            AdminLogService adminLogService = (AdminLogService) MyApplicationContext.a().getBean("adminLogService");
            adminLogService.addAdminLog(adminLog);
            if (admin.getType() == 4) {
                com.miracle9.game.util.GameParameterAssist.bv = false;
            }
        }
        if (com.miracle9.game.util.GameParameterAssist.bd.containsKey(session)) {
            com.miracle9.game.util.GameParameterAssist.bd.remove(session);
        }
    }

    public void sessionCreated(IoSession arg0) throws Exception {
        System.out.println("管理后台服务器和管理后台客户端的连接建立了....");
    }

    public void sessionIdle(IoSession session, IdleStatus arg1) throws Exception {
        this.logger.info("sessionIdle...");
        session.close(true);
    }

    public void sessionOpened(IoSession session) throws Exception {
        String clientIP = ((InetSocketAddress) session.getRemoteAddress()).getAddress().getHostAddress();
        session.setAttribute("ip", clientIP);
        this.logger.info("管理后台服务器和管理后台客户端的连接打开了  sessionOpened, admin IP:" + clientIP);

        ClientIpProcess.startMethod().clientIPSession(session);
    }

}
